package com.haiyou.email.service.impl;

import com.haiyou.common.constant.RedisKeys;
import com.haiyou.common.exception.BusinessException;
import com.haiyou.common.util.RedisUtil;
import com.haiyou.email.model.Email;
import com.haiyou.email.properties.SpringEmailProperties;
import com.haiyou.email.service.SpringEmailService;
import com.haiyou.email.util.DownloadUtil;
import freemarker.template.Template;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 邮箱服务实现
 */
@Slf4j
@RequiredArgsConstructor
public class SpringEmailServiceImpl implements SpringEmailService {

    private final SpringEmailProperties springEmailProperties;
    private final JavaMailSender javaMailSender;
    /**
     * freemarker---FreeMarkerConfigurer
     */
    private final FreeMarkerConfigurer configuration;
    private final RedisUtil redisUtil;

    @Override
    public void sendText(Email mail) {
        try {
            log.info("发送普通文本邮件：{}", mail);
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(springEmailProperties.getUsername());
            message.setTo(mail.getEmail());
            message.setSubject(mail.getSubject());
            message.setText(mail.getContent());
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("-->发送异常：{}", e.getMessage());
        }
    }

    @Override
    public void sendFreemarker(Email mail) {
        try {
            log.info("发送html邮件：{}", mail);
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //这里可以自定义发信名称比如：工作流
            helper.setFrom(springEmailProperties.getUsername(), springEmailProperties.getSenderAlias());
            helper.setTo(mail.getEmail());
            helper.setSubject(mail.getSubject());
            Map<String, Object> model = new HashMap<>();
            model.put("mail", mail);
            model.put("exception", mail.getKvMap());
            Template template = configuration.getConfiguration().getTemplate(mail.getTemplate());
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            helper.setText(text, true);
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("-->发送异常：{}", e.getMessage());
        }
    }

    @Override
    public void sendValidCode(String receiver, String subject, String content) {
        Email mail = new Email();
        mail.setEmail(new String[]{receiver});
        mail.setSubject(subject);
        String sendCode = getSendCode();
        mail.setContent(content.replace("code", sendCode));
        sendText(mail);
        redisUtil.set(RedisKeys.getEmailKey(receiver), Integer.valueOf(sendCode), RedisKeys.EMAIL_CODE_EXPIRE);
    }

    @Override
    public void validEmailCode(String email, String validCode) {
        String emailKey = RedisKeys.getEmailKey(email);
        //邮箱验证码校验
        String redisEmailCode = redisUtil.get(emailKey);
        if (redisEmailCode == null) {
            throw new BusinessException("邮箱验证码已过期");
        }
        if (!redisEmailCode.equals(validCode)) {
            throw new BusinessException("邮箱验证码输入错误");
        }
        redisUtil.delete(emailKey);
    }

    @Override
    public void batchSendEmail(String[] receivers, String subject, String content) {
        this.batchSendEmail(receivers, subject, content, null);
    }

    /**
     * 发送带附件的邮件
     *
     * @param receivers   接收者
     * @param subject     主题
     * @param content     内容
     * @param urlPathList 文件url地址
     */
    @Override
    public void batchSendEmail(String[] receivers, String subject, String content, List<String> urlPathList) {
        log.info("springEmailProperties:{}--->", springEmailProperties);
        log.info("receivers:{}---->", receivers);
        log.info("subject:{}---->", subject);
        log.info("content:{}----->", content);
        log.info("urlPathList:{}----->", urlPathList);

        MimeMessage message = javaMailSender.createMimeMessage();
        try {
            log.info("---------->发送邮件");
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(springEmailProperties.getUsername(), springEmailProperties.getSenderAlias());
            helper.setTo(receivers);
            helper.setSubject(subject);
            helper.setText(content);
            /* 创建用于组合邮件正文和附件的MimeMultipart对象 */
            MimeMultipart multipart = new MimeMultipart();
            // 设置HTML内容
            MimeBodyPart htmlContent = createContent(content);
            multipart.addBodyPart(htmlContent);

            message.setContent(multipart);


            if (urlPathList != null) {
                for (String url : urlPathList) {
                    String filePath = DownloadUtil.downloadFromUrl(url, springEmailProperties.getSavePath());
                    log.info("filePath---->{}", filePath);
                    if (filePath == null) {
                        continue;
                    }
                    FileSystemResource file = new FileSystemResource(new File(URLDecoder.decode(filePath, "UTF-8")));
                    String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
                    log.info("附件名称={}-------->", fileName);
                    helper.addAttachment(fileName, file);
                }
            }

            javaMailSender.send(message);
            log.info("邮件发送成功---------->");
        } catch (Exception e) {
            log.info("发送邮件失败：{}---------->", e);
        }
    }

    /**
     * 创建HTML格式的邮件内容
     *
     * @param body 邮件内容
     * @return 邮件内容实体
     * @throws Exception
     */
    private static MimeBodyPart createContent(String body) throws Exception {

        /* 创建代表组合MIME消息的MimeMultipart对象和该对象保存到的MimeBodyPart对象 */
        MimeBodyPart content = new MimeBodyPart();

        // 创建一个MImeMultipart对象
        MimeMultipart multipart = new MimeMultipart();

        // 创建一个表示HTML正文的MimeBodyPart对象，并将它加入到前面的创建的MimeMultipart对象中
        MimeBodyPart htmlBodyPart = new MimeBodyPart();
        htmlBodyPart.setContent(body.replaceAll("\n", "<br/>"), "text/html;charset=UTF-8");
        multipart.addBodyPart(htmlBodyPart);

        // 将MimeMultipart对象保存到MimeBodyPart对象中
        content.setContent(multipart);

        return content;
    }

    private String getSendCode() {
        int x = new Random().nextInt(1000000);
        return String.valueOf(x);
    }
}
